// © 2016 and later: Unicode, Inc. and others.
// License & terms of use: http://www.unicode.org/copyright.html
/*
 *******************************************************************************
 * Copyright (C) 1996-2010, International Business Machines Corporation and    *
 * others. All Rights Reserved.                                                *
 *******************************************************************************
 */
package com.ibm.icu.dev.test.normalizer;

import com.ibm.icu.dev.test.CoreTestFmwk;
import com.ibm.icu.impl.Utility;
import com.ibm.icu.lang.UCharacter;
import com.ibm.icu.lang.UProperty;
import com.ibm.icu.text.ComposedCharIter;
import com.ibm.icu.text.Normalizer;
import com.ibm.icu.text.StringCharacterIterator;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.JUnit4;

@RunWith(JUnit4.class)
public class TestDeprecatedNormalizerAPI extends CoreTestFmwk {
    public TestDeprecatedNormalizerAPI() {}

    @Test
    public void TestNormalizerAPI() {
        // instantiate a Normalizer from a CharacterIterator
        String s = Utility.unescape("a\u0308\uac00\\U0002f800");
        // make s a bit longer and more interesting
        java.text.CharacterIterator iter = new StringCharacterIterator(s + s);
        // test deprecated constructors
        Normalizer norm = new Normalizer(iter, Normalizer.NFC, 0);
        if (norm.next() != 0xe4) {
            errln("error in Normalizer(CharacterIterator).next()");
        }
        Normalizer norm2 = new Normalizer(s, Normalizer.NFC, 0);
        if (norm2.next() != 0xe4) {
            errln("error in Normalizer(CharacterIterator).next()");
        }
        // test clone(), ==, and hashCode()
        Normalizer clone = norm.clone();
        if (clone.getBeginIndex() != norm.getBeginIndex()) {
            errln("error in Normalizer.getBeginIndex()");
        }

        if (clone.getEndIndex() != norm.getEndIndex()) {
            errln("error in Normalizer.getEndIndex()");
        }
        // test setOption() and getOption()
        clone.setOption(0xaa0000, true);
        clone.setOption(0x20000, false);
        if (clone.getOption(0x880000) == 0 || clone.getOption(0x20000) == 1) {
            errln("error in Normalizer::setOption() or Normalizer::getOption()");
        }
        // test deprecated normalize method
        Normalizer.normalize(s, Normalizer.NFC, 0);
        // test deprecated compose method
        Normalizer.compose(s, false, 0);
        // test deprecated decompose method
        Normalizer.decompose(s, false, 0);
    }

    /**
     * Run through all of the characters returned by a composed-char iterator and make sure that:
     *
     * <ul>
     *   <li>a) They do indeed have decompositions.
     *   <li>b) The decomposition according to the iterator is the same as returned by
     *       Normalizer.decompose().
     *   <li>c) All characters <em>not</em> returned by the iterator do not have decompositions.
     * </ul>
     */
    @Test
    public void TestComposedCharIter() {
        doTestComposedChars(false);
    }

    private void doTestComposedChars(boolean compat) {
        int options = Normalizer.IGNORE_HANGUL;
        ComposedCharIter iter = new ComposedCharIter(compat, options);

        char lastChar = 0;

        while (iter.hasNext()) {
            char ch = iter.next();

            // Test all characters between the last one and this one to make
            // sure that they don't have decompositions
            assertNoDecomp(lastChar, ch, compat, options);
            lastChar = ch;

            // Now make sure that the decompositions for this character
            // make sense
            String chString = new StringBuffer().append(ch).toString();
            String iterDecomp = iter.decomposition();
            String normDecomp = Normalizer.decompose(chString, compat);

            if (iterDecomp.equals(chString)) {
                errln("ERROR: " + hex(ch) + " has identical decomp");
            } else if (!iterDecomp.equals(normDecomp)) {
                errln(
                        "ERROR: Normalizer decomp for "
                                + hex(ch)
                                + " ("
                                + hex(normDecomp)
                                + ")"
                                + " != iter decomp ("
                                + hex(iterDecomp)
                                + ")");
            }
        }
        assertNoDecomp(lastChar, '\uFFFF', compat, options);
    }

    void assertNoDecomp(char start, char limit, boolean compat, int options) {
        for (char x = ++start; x < limit; x++) {
            String xString = new StringBuffer().append(x).toString();
            String decomp = Normalizer.decompose(xString, compat);
            if (!decomp.equals(xString)) {
                errln(
                        "ERROR: "
                                + hex(x)
                                + " has decomposition ("
                                + hex(decomp)
                                + ")"
                                + " but was not returned by iterator");
            }
        }
    }

    @Test
    public void TestRoundTrip() {
        int options = Normalizer.IGNORE_HANGUL;
        boolean compat = false;

        ComposedCharIter iter = new ComposedCharIter(false, options);
        while (iter.hasNext()) {
            final char ch = iter.next();

            String chStr = String.valueOf(ch);
            String decomp = iter.decomposition();
            String comp = Normalizer.compose(decomp, compat);

            if (UCharacter.hasBinaryProperty(ch, UProperty.FULL_COMPOSITION_EXCLUSION)) {
                logln("Skipped excluded char " + hex(ch) + " (" + UCharacter.getName(ch) + ")");
                continue;
            }

            // Avoid disparaged characters
            if (decomp.length() == 4) continue;

            if (!comp.equals(chStr)) {
                errln(
                        "ERROR: Round trip invalid: "
                                + hex(chStr)
                                + " --> "
                                + hex(decomp)
                                + " --> "
                                + hex(comp));

                errln("  char decomp is '" + decomp + "'");
            }
        }
    }
}
